package com.allinpay.merchantweb.common.utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 数据结构转换工具
 * 
 * @author xiaosw 2014-12-8
 */
public class DataStructureUtil {
    public static Map<String, Object> bean2Map(Object obj) throws Exception {
        String errorMessage = "The operation of bean2Map has been error!";
        Map<String, Object> map = null;
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            map = objectMapper.readValue(bean2JSON(obj), Map.class);
        } catch (JsonParseException e) {
            throw new Exception(errorMessage, e);
        } catch (JsonMappingException e) {
            throw new Exception(errorMessage, e);
        } catch (IOException e) {
            throw new Exception(errorMessage, e);
        }
        return map;
    }

    public static <T> T map2Bean(Map map, Class clz) throws Exception {
        String errorMessage = "The operation of map2Bean has been error!";
        try {

            Object obj = clz.newInstance(); // 创建 JavaBean 对象
            BeanInfo beanInfo = Introspector.getBeanInfo(clz);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor descriptor : propertyDescriptors) {
                String propertyName = descriptor.getName();
                if (map.containsKey(propertyName)) {
                    Object value = map.get(propertyName);
                    if (descriptor.getWriteMethod() != null) {
                        descriptor.getWriteMethod().invoke(obj, value);
                    }
                }
            }
            return (T) obj;
        } catch (IntrospectionException e) {
            throw new Exception(errorMessage, e);
        } catch (IllegalArgumentException e) {
            throw new Exception(errorMessage, e);
        } catch (IllegalAccessException e) {
            throw new Exception(errorMessage, e);
        } catch (InvocationTargetException e) {
            throw new Exception(errorMessage, e);
        } catch (InstantiationException e) {
            throw new Exception(errorMessage, e);
        }
    }

    public static String bean2JSON(Object obj) throws Exception {
        String errorMessage = "The operation of bean2Json has been error!";
        ObjectMapper objectMapper = null;
        StringBuffer strBuffer = new StringBuffer("");
        objectMapper = new ObjectMapper();
        try {
            strBuffer.append(objectMapper.writeValueAsString(obj));
        } catch (JsonGenerationException e) {
            throw new Exception(errorMessage, e);
        } catch (JsonMappingException e) {
            throw new Exception(errorMessage, e);
        } catch (IOException e) {
            throw new Exception(errorMessage, e);
        }
        return strBuffer.toString();
    }

    public static <T> T json2Bean(String json, Class clz) throws Exception {
        String errorMessage = "The operation of json2Bean has been error!";
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            return (T) objectMapper.readValue(json, clz);
        } catch (JsonParseException e) {
            throw new Exception(errorMessage, e);
        } catch (JsonMappingException e) {
            throw new Exception(errorMessage, e);
        } catch (IOException e) {
            throw new Exception(errorMessage, e);
        }
    }

    // Bean --> Map : 利用Introspector和PropertyDescriptor 将Bean --> Map
    public static Map<String, Object> transBean2Map(Object obj) {

        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();

                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);

                    map.put(key, value);
                }

            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }
        return map;
    }
}
